﻿using System;
using System.IO;
using System.Linq;
using System.Web.Mvc;
using System.Web.Routing;
using GmaWebService.Interfaces;
using MPWebStream.MediaTranscoding;
using TV4Home.Server.TVEInteractionLibrary.Interfaces;
using WebMediaPortal.Models;
using WebMediaPortal.Services;

namespace WebMediaPortal.Controllers
{
    public class StreamController : Controller
    {
        //
        // GET: /Stream/
        public ActionResult Index()
        {
            return View();
        }

        //
        // Streams
        public ActionResult TV(int item, string transcoder, string size)
        {
            WebChannelBasic channel = WebServices.TVService.GetChannelBasicById(item);
            string username = "WebMediaPortal";
            WebVirtualCard card = WebServices.TVService.SwitchTVServerToChannelAndGetVirtualCard(username, channel.IdChannel);
            GenerateStream(card.TimeShiftFileName, transcoder, size); // don't use the special TV constructor of MPWebStream here because it's buggy
            WebServices.TVService.CancelCurrentTimeShifting(username);
            return new EmptyResult();
        }

        public ActionResult Movie(int item, string transcoder, string size)
        {
            WebMovieFull movie = WebServices.MediaAccessService.GetFullMovie(item);
            return GenerateStream(movie.Filename, transcoder, size);
        }

        public ActionResult Serie(int item, string transcoder, string size)
        {
            WebEpisodeFull episode = WebServices.MediaAccessService.GetFullEpisode(item);
            return GenerateStream(episode.EpisodeFile.FileName, transcoder, size);
        }

        // Player
        public ActionResult Player(StreamMedia type, string itemId)
        {
            // transcoder config
            string transcoderName = Request.Params["player"] != null ? Request.Params["player"] : "flash-lq";
            TranscoderModel transcoder = GetTranscoderProfile(transcoderName);
            string viewName = Enum.GetName(typeof(VideoPlayer), transcoder.Player) + "Player";

            // player size, assume 16:9 by default
            decimal aspect;
            if(type != StreamMedia.TV) {
                aspect = WebServices.MediaAccessService.GetMediaInfo((MediaItemType)type, itemId).DisplayAspectRatio;
            } else {
                aspect = (decimal)16 / 9; // assume 16:9 for tv
            }
            Resolution playerSize = Resolution.Calculate(aspect, new Resolution(transcoder.MaxOutputWidth, transcoder.MaxOutputHeight), 2);

            // generate url
            RouteValueDictionary parameters = new RouteValueDictionary();
            parameters["item"] = itemId;
            parameters["transcoder"] = transcoderName;
            parameters["size"] = playerSize;

            // generate view
            return PartialView(viewName, new StreamModel
            {
                URL = Url.Action(Enum.GetName(typeof(StreamMedia), type), parameters),
                Size = playerSize
            });
        }

        //
        // Helper methods
        private TranscoderModel GetTranscoderProfile(string transcoderProfile = null)
        {
            return TranscoderModel.List().Where(t => t.Name == transcoderProfile).FirstOrDefault();
        }

        protected TranscoderModel PrepareTranscoder(string transcoderProfile, string size) 
        {
            TranscoderModel transcoder = GetTranscoderProfile(transcoderProfile);
            transcoder.Parameters = string.Format(
                "-y -i {0} -s {1} -aspect {2} {3} -f {4} {5}",
                "\"{0}\"",
                size,
                size.ToString().Replace("x", ":"),
                transcoder.CodecParameters,
                "flv",
                "\"{1}\""
            );

            // make paths relative to the dir where config.transcoder.xml is
            if (Path.GetFullPath(transcoder.Transcoder) != transcoder.Transcoder)
                transcoder.Transcoder = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, transcoder.Transcoder));
            WebMediaPortal.Code.Log.Info("Path to ffmpeg: " + transcoder.Transcoder);
            WebMediaPortal.Code.Log.Info("FFmpeg arguments: " + transcoder.Parameters);

            return transcoder;
        }

        protected ActionResult GenerateStream(string source, string transcoderProfile, string size) 
        {
            TranscodingStreamer streamer = new TranscodingStreamer(source, PrepareTranscoder(transcoderProfile, size));
            streamer.StartTranscoding();
            streamer.TranscodeToClient(Response);
            return new EmptyResult();
        }
    }
}